﻿
namespace DatabaseDoc.Outputters.BasicHtml
{
    using System;
    using System.IO;
    using System.Reflection;
    using System.Text;

    using DatabaseDoc.Library;

    /// <summary>
    /// Basic HTML outputter
    /// Outputs to an HTML5 document using a simple layout
    /// </summary>
    public class BasicHttpOutputter : IOutputter
    {
        /// <summary>
        /// Gets the key.
        /// </summary>
        /// <value>The key.</value>
        public string Key
        {
            get
            {
                return "BASICHTML";
            }
        }

        /// <summary>
        /// Outputs the specified database doc.
        /// </summary>
        /// <param name="databaseDoc">The database doc.</param>
        /// <param name="fileName">Name of the file.</param>
        public void Output(DatabaseDoc databaseDoc, string fileName)
        {
            if (databaseDoc == null)
            {
                return;
            }

            if (databaseDoc.Servers == null)
            {
                return;
            }

            var stringBuilder = new StringBuilder();
            stringBuilder.AppendLine("<!DOCTYPE html>");
            stringBuilder.AppendLine("<html>");
            stringBuilder.AppendLine("<head>");
            stringBuilder.AppendFormat("<title>{0}</title>", "Report");
            stringBuilder.AppendLine();
            stringBuilder.Append(EmbedCss());
            stringBuilder.AppendLine();
            stringBuilder.AppendLine("</head>");
            stringBuilder.AppendLine("<body>");

            for (var i = 0; i < databaseDoc.Servers.Count; i++)
            {
                var server = databaseDoc.Servers[i];
                var lastServer = i == databaseDoc.Servers.Count - 1;

                stringBuilder.AppendFormat("<h1>{0}</h1>", server.Name);

                if (server.Databases != null)
                {
                    foreach (var database in server.Databases)
                    {
                        stringBuilder.AppendFormat("<h2>{0}</h2>", database.Name);

                        if (database.Tables != null)
                        {                           
                            foreach (var table in database.Tables)
                            {
                                stringBuilder.AppendLine("<table class=\"sql-table\">");
                                stringBuilder.AppendFormat("<caption>{0}</caption>", table.Name);
                                stringBuilder.AppendLine();

                                stringBuilder.AppendLine("<thead>");
                                stringBuilder.AppendLine("<tr>");
                                stringBuilder.AppendLine("<th scope=\"col\">Name</th>");
                                stringBuilder.AppendLine("<th scope=\"col\">Type</th>");
                                stringBuilder.AppendLine("<th scope=\"col\">Size</th>");
                                stringBuilder.AppendLine("<th scope=\"col\">Nullable</th>");
                                stringBuilder.AppendLine("</tr>");
                                stringBuilder.AppendLine("</thead>");

                                stringBuilder.AppendLine("<tbody>");

                                foreach (var column in table.Columns)
                                {
                                    stringBuilder.AppendLine("<tr>");
                                    stringBuilder.AppendFormat("<td>{0}</td>", column.Name);
                                    stringBuilder.AppendFormat("<td>{0}</td>", column.DataType);
                                    stringBuilder.AppendFormat("<td>{0}</td>", column.DataTypeSize);
                                    stringBuilder.AppendFormat("<td>{0}</td>", column.Nullable ? "NULL" : "NOT NULL");
                                    stringBuilder.AppendLine("</tr>");
                                }

                                stringBuilder.AppendLine("</tbody>");

                                stringBuilder.AppendLine("</table>");
                            }
                        }

                        stringBuilder.AppendLine();
                    }
                }

                if (!lastServer)
                {
                    stringBuilder.AppendLine();
                }
            }

            stringBuilder.AppendLine("</body>");
            stringBuilder.Append("</html>");

            // Create a file to write to
            var filePath = string.Format("{0}.html", fileName);
            using (var sw = File.CreateText(filePath))
            {
                sw.Write(stringBuilder.ToString());
            }
        }

        private static string EmbedCss()
        {
            var assembly = Assembly.GetCallingAssembly();

            using (var stream = assembly.GetManifestResourceStream("DatabaseDoc.Outputters.BasicHtml.style.css"))
            {
                if (stream == null)
                {
                    return string.Empty;
                }
                
                using (var reader = new StreamReader(stream))
                {
                    var result = string.Format("<style media=\"screen\" type=\"text/css\">{0}</style>", reader.ReadToEnd());
                    return result;
                }
            }
        }
    }
}